package com.yonyou.pmclouds.personnel.service.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoInsertMultiProcessor;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoUpdateProcessor;
import com.yonyou.pmclouds.basecom.bp.template.MultiDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.MultiInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.enterprise.entity.EnterpriseVO;
import com.yonyou.pmclouds.enterprise.mapper.EnterpriseMapper;
import com.yonyou.pmclouds.enterprise.rmiitf.EnterpriseMaintain;
import com.yonyou.pmclouds.outter.tenantsdk.entity.TenantSdkUserInfo;
import com.yonyou.pmclouds.outter.tenantsdk.rmiitf.IUserInfoService;
import com.yonyou.pmclouds.personnel.entity.PersonnelVO;
import com.yonyou.pmclouds.personnel.mapper.PersonnelMapper;
import com.yonyou.pmclouds.personnel.process.DeleteCheckBeforeProcess;
import com.yonyou.pmclouds.personnel.process.PhoneAndEmailCheckBeforeProcess;
import com.yonyou.pmclouds.personnel.process.YhtUserRefBeforeMultiProcess;
import com.yonyou.pmclouds.personnel.process.YhtUserRefBeforeProcess;
import com.yonyou.pmclouds.personnel.rmiitf.PersonnelMaintain;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.MessageFormat;
import java.util.*;

/**
 * @Author chulf
 * @Date 2020/4/15
 * @Description
 **/
@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = PersonnelMaintain.class)
public class PersonnelMaintainImpl implements PersonnelMaintain {

    public static final String UPDATE_DATA_KEY = "updateData";
    public static final String ADD_DATA_KEY = "addData";
    public static final String DELETE_DATA_KEY = "deleteData";
    public static final String ON = "on";
    public static final String OFF = "off";

    public static final int DR_FLAG = 1;
    public static final int IS_CONTACT_FLAG = 1;
    public static final String[] UPDATE_FIELDS = {PersonnelVO.EMAIL, PersonnelVO.PHONE, PersonnelVO.USER_NAME, PersonnelVO.MEMO, PersonnelVO.IS_CONTACTS, PersonnelVO.IS_SPECIAL_WORK,
            PersonnelVO.IS_YGC_AUTHORIZER, PersonnelVO.USER_ID};

    @Autowired
    private PersonnelMapper personnelMapper;
    @Autowired
    private YhtUserRefBeforeMultiProcess yhtUserRefBeforeMultiProcess;
    @Autowired
    private YhtUserRefBeforeProcess yhtUserRefBeforeProcess;
    @Autowired
    private IUserInfoService iUserInfoService;
    @Autowired
    private EnterpriseMapper enterprisemapper;
    @Autowired
    private EnterpriseMaintain enterpriseMaintain;

    @Override
    public ArrayList<PersonnelVO> savePersonnels(PersonnelVO[] personnelVOS) throws BusinessException {

        EnterpriseVO[] enterpriseVOS = enterprisemapper.selectEtpsByPks(new String[]{personnelVOS[0].getPkEnterprise()});
        EnterpriseVO enterpriseVO = enterpriseVOS[0];
        int personnelNum = enterpriseVO.getPersonnelNum() == null ? 0 : enterpriseVO.getPersonnelNum();

        //区分新增和修改和删除
        Map<String, List<PersonnelVO>> datas = splitDatas(personnelVOS);

        //校验新增和修改中是否只有一个企业联系人
        ArrayList<PersonnelVO> checkData = new ArrayList<>();
        if (datas.get(ADD_DATA_KEY) != null) checkData.addAll(datas.get(ADD_DATA_KEY));
        if (datas.get(UPDATE_DATA_KEY) != null) checkData.addAll(datas.get(UPDATE_DATA_KEY));
        checkUniqueContact(checkData);

        List<PersonnelVO> addData = datas.get(ADD_DATA_KEY);
        if (addData != null && !addData.isEmpty()) {
            MultiInsertBpTemplate<PersonnelVO> bp = new MultiInsertBpTemplate<>(personnelMapper);
            bp.addBeforeProcessor(new AuditInfoInsertMultiProcessor<>());

            //手机号或邮箱为空校验
            bp.addBeforeProcessor(new PhoneAndEmailCheckBeforeProcess());
            //新增进行友互通用户关联
            bp.addBeforeProcessor(yhtUserRefBeforeMultiProcess);

            bp.insert(addData.toArray(new PersonnelVO[0]));

            personnelNum += addData.size();
        }
        List<PersonnelVO> updateData = datas.get(UPDATE_DATA_KEY);
        if (updateData != null && !updateData.isEmpty()) {
            SingleUpdateBpTemplate<PersonnelVO> bp = new SingleUpdateBpTemplate<PersonnelVO>(personnelMapper, UPDATE_FIELDS);
            bp.addBeforeProcessor(new AuditInfoUpdateProcessor<PersonnelVO>());
            //手机号或邮箱为空校验
            bp.addBeforeProcessor(new PhoneAndEmailCheckBeforeProcess());

            for (PersonnelVO updateDatum : updateData) {
                bp.update(updateDatum);
            }
        }
        List<PersonnelVO> deleteData = datas.get(DELETE_DATA_KEY);
        if (deleteData != null && !deleteData.isEmpty()) {
            MultiDeleteBpTemplate<PersonnelVO> bp = new MultiDeleteBpTemplate<PersonnelVO>(personnelMapper, true);

            //校验删除用户是否包含友互通权限
            bp.addBeforeProcessor(new DeleteCheckBeforeProcess());
            bp.delete(deleteData.toArray(new PersonnelVO[0]));

            personnelNum -= deleteData.size();
        }
        //修改人员总数
        enterpriseVO.setPersonnelNum(personnelNum);
        enterpriseMaintain.updateEnterprise(enterpriseVO);

        //将修改和添加人员数据返回
        ArrayList<PersonnelVO> result = new ArrayList<>();
        if (addData != null) result.addAll(addData);
        if (updateData != null) result.addAll(updateData);
        return result;
    }

    @Override
    public void editOnOffPersonnel(PersonnelVO[] personnelVOS, String onOff) throws BusinessException {

        //校验数据是否是最新数据
        checkDataChangeFlag(personnelVOS);

        //用于批量 修改是否授权
        PersonnelVO personnelVO = personnelVOS[0]; //取一个作为标准
        personnelVO.setChangeFlag(UUID.randomUUID().toString());

        //授权完成后对企业实际授权数修改
        EnterpriseVO[] enterpriseVOS = enterprisemapper.selectEtpsByPks(new String[]{personnelVO.getPkEnterprise()});
        EnterpriseVO enterpriseVO = enterpriseVOS[0];
        Integer realAuthorizedNum = enterpriseVO.getRealAuthorizedNum();

        HashSet<String> pks = new HashSet<>();
        for (PersonnelVO vo : personnelVOS) {
            pks.add(vo.getPkPersonnel());
        }
        if (ON.equalsIgnoreCase(onOff)) {

            //授权数计算
            enterpriseVO.setRealAuthorizedNum(realAuthorizedNum == null ? 0 + pks.size() : realAuthorizedNum + pks.size());

            if (enterpriseVO.getRealAuthorizedNum() > enterpriseVO.getPlanAuthorizedNum())
                throw new BusinessException("实际授权数不能大于计划授权数");

            //授权
            TenantSdkUserInfo[] tenantSdkUserInfos = creatSdkUserByPersonel(personnelVOS);

            TenantSdkUserInfo[] sdkUserInfos = iUserInfoService.addUsersAndRelations(tenantSdkUserInfos);

            //批量授权  这里考虑性能问题暂时不做数据锁控制 且操作授权的人也不需要关心
            personnelVO.setIsYgcAuthorizer((byte) 1);
        }
        if (OFF.equalsIgnoreCase(onOff)) {
            //取消授权
            HashSet<String> userIds = new HashSet<>();
            for (PersonnelVO tempPersonnelVO : personnelVOS) {
                userIds.add(tempPersonnelVO.getUserId());
            }
            iUserInfoService.removeUsersFromApps(userIds.toArray(new String[0]));

            //批量取消授权
            personnelVO.setIsYgcAuthorizer((byte) 0);

            //取消授权完成后对企业实际授权数修改
            enterpriseVO.setRealAuthorizedNum(enterpriseVO.getRealAuthorizedNum() - pks.size());
        }
        personnelMapper.updateAuthorized(personnelVO, new String[]{PersonnelVO.IS_YGC_AUTHORIZER}, pks.toArray(new String[0]));
        enterpriseMaintain.updateEnterprise(enterpriseVO);
    }

    /**
     * @param personnels
     * @return 将新增/修改/删除 数据区分
     */
    private Map<String, List<PersonnelVO>> splitDatas(PersonnelVO[] personnels) {

        HashMap<String, List<PersonnelVO>> splitData = new HashMap<>();
        for (PersonnelVO personnel : personnels) {
            if (StringUtils.isNotEmpty(personnel.getPkPersonnel())) {
                //主键不为空为修改和删除
                if (personnel.getDr() == DR_FLAG) {
                    if (splitData.get(DELETE_DATA_KEY) == null)
                        splitData.put(DELETE_DATA_KEY, new ArrayList<PersonnelVO>());
                    splitData.get(DELETE_DATA_KEY).add(personnel);
                } else {
                    if (splitData.get(UPDATE_DATA_KEY) == null)
                        splitData.put(UPDATE_DATA_KEY, new ArrayList<PersonnelVO>());
                    splitData.get(UPDATE_DATA_KEY).add(personnel);
                }
            } else {

                if (splitData.get(ADD_DATA_KEY) == null)
                    splitData.put(ADD_DATA_KEY, new ArrayList<PersonnelVO>());

                //新增时设置原始手机号及邮箱
                personnel.setOriginalPhone(personnel.getPhone());
                personnel.setOriginalEmail(personnel.getEmail());
                splitData.get(ADD_DATA_KEY).add(personnel);
            }
        }

        return splitData;
    }

    /**
     * @param personnelVOS
     * @return 构建yht 用户信息
     */
    public static TenantSdkUserInfo[] creatSdkUserByPersonel(PersonnelVO[] personnelVOS) {

        ArrayList<TenantSdkUserInfo> result = new ArrayList<>();
        for (PersonnelVO personnelVO : personnelVOS) {
            TenantSdkUserInfo sdkUserInfo = new TenantSdkUserInfo();
            sdkUserInfo.setUserName(personnelVO.getSname());
            sdkUserInfo.setUserMobile(personnelVO.getOriginalPhone());
            sdkUserInfo.setUserEmail(personnelVO.getOriginalEmail());
            result.add(sdkUserInfo);
        }

        return result.toArray(new TenantSdkUserInfo[0]);
    }

    /**
     * 校验同一批人员中不能存在多个企业联系人
     *
     * @param personnelVOS
     */
    private void checkUniqueContact(List<PersonnelVO> personnelVOS) throws BusinessException {

        boolean hasConcat = false;
        for (PersonnelVO personnelVO : personnelVOS) {
            if (IS_CONTACT_FLAG == (personnelVO.getIsContacts())) {
                if (!hasConcat) hasConcat = true;
                else throw new BusinessException("同一个企业中只能有一个企业联系人");
            }

        }
    }

    /**
     * 数据修改乐观锁比较
     *
     * @param personnelVOS
     * @throws BusinessException
     */
    private void checkDataChangeFlag(PersonnelVO[] personnelVOS) throws BusinessException {

        if (ArrayUtils.isEmpty(personnelVOS)) return;
        HashMap<String, PersonnelVO> pk2Personnel = new HashMap<>();
        for (PersonnelVO personnelVO : personnelVOS) {
            pk2Personnel.put(personnelVO.getPkPersonnel(), personnelVO);
        }
        PersonnelVO[] personnels = personnelMapper.selectPersonnelVOSByPks(pk2Personnel.keySet().toArray(new String[0]));

        for (PersonnelVO personnel : personnels) {
            if (!personnel.getChangeFlag().equalsIgnoreCase(pk2Personnel.get(personnel.getPkPersonnel()).getChangeFlag())) {
                throw new BusinessException(MessageFormat.format("{0},人员信息已被修改,请刷新后操作!", personnel.getSname()));
            }
        }
    }

    @Override
    public PersonnelVO[] insertBatchByTeam(PersonnelVO[] personnelVOS) throws BusinessException {
        if(personnelVOS == null || personnelVOS.length <= 0){
            return null;
        }
        MultiInsertBpTemplate<PersonnelVO> bp = new MultiInsertBpTemplate<>(personnelMapper);
        bp.addBeforeProcessor(new AuditInfoInsertMultiProcessor<>());
        //设置原始手机号及邮箱
        for (PersonnelVO personnelVO : personnelVOS) {
            personnelVO.setOriginalPhone(personnelVO.getPhone());
            personnelVO.setOriginalEmail(personnelVO.getEmail());
        }
        return bp.insert(personnelVOS);
    }
}
